package concurrency.exclusion_mutuelle.v_synchronized;

public class ExclusionMutuelleObjet {
	
	private long varPartagee;
	private Object mutex = new Object(); // Verrour servant pour la section critique
	
	public ExclusionMutuelleObjet() {
		varPartagee = 0;
	}
	
	public void incremente() {
		// On considere le verrou de l'objet mutex qui n'est la que pour ca !!
		// On N'utilise PAS le verrou associe a l'objet courant this :)
		// Cela permet de ne pas bloquer le verrou de l'instance courante :)
		synchronized (mutex) {
			// Debut SC 
			varPartagee++;
			description();
			// Fin SC
		}
	}
	
	public void decremente() {
		synchronized (mutex) {
			// Debut SC
			varPartagee--;
			description();
			// Fin SC
		}
	}
	
	public void description() {
		String des = Thread.currentThread().getName() + " VAR : " + varPartagee;
		System.out.println(des);
	}
	
	private class Processus extends Thread {
		
		private final int repetition;
		private final boolean incrementeOp;
		
		public Processus(final String name, final int repetition, final boolean incrementeOp) {
			setName(name);
			this.repetition = repetition;
			this.incrementeOp = incrementeOp;
		}
		
		@Override
		public void run() {
			for (int i = 0; i < repetition; i++) {
				if (incrementeOp) {
					incremente();					
				} else {
					decremente();
				}
				Thread.yield(); // Permet de ceder la main à un autre thread :)
			}
		}
	}
	
	public static void main(String[] args) {
		ExclusionMutuelleObjet ex = new ExclusionMutuelleObjet();
		Processus p1 = ex.new Processus("Thread_1", 1000, true);
		Processus p2 = ex.new Processus("Thread_2", 1000, false);
		p1.start();
		p2.start();
	}
}
